﻿using System.Collections.Generic;
using System.Data;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RomanNumeralKata.Core;
using RomanNumeralKata.Core.Utility;

namespace RomanNumeralKata.Tests.RomanNumeralKata
{
    /// <summary>
    /// man I wish mstest had parameterized/test case tests
    /// </summary>
    public class ConverterTestBase
    {
        private static Dictionary<int, string> _testData = new Dictionary<int, string>()
        {
            {0, ""},
            {1, "I"}
            //etc...
        };  

        protected IRomanNumeralConverter _converter;
        protected IRomanNumeralValidator _validator;

        public ConverterTestBase(IRomanNumeralConverter converter)
        {
            _converter = converter;
            _validator = new RomanNumeralRegExValidator(); // to check all
        }

        [TestMethod]
        public void ConvertArabicToRomanNumeralSingleDigitOneTest()
        {
            int number = 1;
            string result = _converter.ConvertArabicToRomanNumeral(number);

            Assert.AreEqual("I", result, result + " was not equal to expected I");
        }

        [TestMethod]
        public void ConvertArabicToRomanNumeralSingleDigitFiveTest()
        {
            int number = 5;
            string result = _converter.ConvertArabicToRomanNumeral(number);

            Assert.AreEqual("V", result, result + " was not equal to expected V");
        }

        [TestMethod]
        public void ConvertArabicToRomanNumeralSingleDigitTenTest()
        {
            int number = 10;
            string result = _converter.ConvertArabicToRomanNumeral(number);

            Assert.AreEqual("X", result, result + " was not equal to expected X");
        }

        [TestMethod]
        public void ConvertArabicToRomanNumeralSingleDigitFiftyTest()
        {
            int number = 50;
            string result = _converter.ConvertArabicToRomanNumeral(number);

            Assert.AreEqual("L", result, result + " was not equal to expected L");
        }

        [TestMethod]
        public void ConvertArabicToRomanNumeralSingleDigit100Test()
        {
            int number = 100;
            string result = _converter.ConvertArabicToRomanNumeral(number);

            Assert.AreEqual("C", result, result + " was not equal to expected C");
        }

        [TestMethod]
        public void ConvertArabicToRomanNumeralSingleDigit500Test()
        {
            int number = 500;
            string result = _converter.ConvertArabicToRomanNumeral(number);

            Assert.AreEqual("D", result, result + " was not equal to expected D");
        }

        [TestMethod]
        public void ConvertArabicToRomanNumeralSingleDigit1000Test()
        {
            int number = 1000;
            string result = _converter.ConvertArabicToRomanNumeral(number);

            Assert.AreEqual("M", result, result + " was not equal to expected M");
        }

        [TestMethod]
        public void ConvertArabicToRomanNumeralSingleDigitFourTest()
        {
            int number = 4;
            string result = _converter.ConvertArabicToRomanNumeral(number);

            Assert.AreEqual("IV", result, result + " was not equal to expected IV");
        }

        [TestMethod]
        public void ConvertArabicToRomanNumeralSingleDigitThreeTest()
        {
            int number = 3;
            string result = _converter.ConvertArabicToRomanNumeral(number);

            Assert.AreEqual("III", result, result + " was not equal to expected III");
        }

        [TestMethod]
        public void ConvertArabicToRomanNumeralSingleDigitNineTest()
        {
            int number = 9;
            string result = _converter.ConvertArabicToRomanNumeral(number);

            Assert.AreEqual("IX", result, result + " was not equal to expected IX");
        }

        [TestMethod]
        public void ConvertArabicToRomanNumeralRandomNumber1455Test()
        {
            int number = 1455;
            string result = _converter.ConvertArabicToRomanNumeral(number);

            Assert.AreEqual("MCDLV", result, result + " was not equal to expected MCDLV");
        }

        [TestMethod]
        public void ConvertArabicToRomanNumeralRandomNumber316Test()
        {
            int number = 316;
            string result = _converter.ConvertArabicToRomanNumeral(number);

            Assert.AreEqual("CCCXVI", result, result + " was not equal to expected CCCXVI");
        }

        [TestMethod]
        public void ConvertArabicToRomanNumerals1Through3999Test()
        {
            // list obtained from http://online-calculators.appspot.com/roman/list/
            string[] allNumerals = File.ReadAllLines("./Resources/RomanNumeralsTo3999.csv");
            foreach (string line in allNumerals)
            {
                string[] arabicRomanTuple = line.Split(',');
                int arabicNumber = int.Parse(arabicRomanTuple[0]);
                string romanNumeral = arabicRomanTuple[1];


                string result = _converter.ConvertArabicToRomanNumeral(arabicNumber);
                bool isValid = _validator.IsValidRomanNumeral(result);
                Assert.AreEqual(romanNumeral, result, result + " was not the expected roman numeral of " + romanNumeral);
                Assert.IsTrue(isValid, result + " Is not a valid roman numeral.");
            }
        }

    }
}
